<template>
  <view class="push-window" @touchstart="onTouchStart" @touchmove.prevent="onTouchMove" @touchend="onTouchEnd">
    <view :class="['push-window-content', this.directions[this.direction].class]" :style="{ transform }">{{
      this.directions[this.direction].info
    }}</view>
  </view>
</template>

<script>
export default {
  data() {
    return {
      startX: 0,
      startY: 0,

      moveX: 0,
      moveY: 0,

      transform: '',
      isShow: false,

      direction: 4,
      directions: {
        0: {
          info: '没动',
          class: '',
        },
        1: {
          info: '下滑关闭 ↓',
          class: 'from_bottom',
        },
        2: {
          info: '上滑关闭 ↑',
          class: 'from_top',
        },
        3: {
          info: '右滑关闭 →',
          class: 'from_right',
        },
        4: {
          info: '← 左滑关闭',
          class: 'from_left',
        },
      },
    }
  },

  methods: {
    onTouchStart(e) {
      this.startX = e.touches[0].clientX
      this.startY = e.touches[0].clientY
    },

    onTouchMove(e) {
      this.moveX = e.touches[0].clientX - this.startX
      this.moveY = e.touches[0].clientY - this.startY

      if (this.isShow) {
        // do something
      } else {
        this.direction = this.getDirection() 
      }
    },

    onTouchEnd() {
      if (this.isShow) {
        switch (this.direction) {
          case 1:
            if (this.getDirection() == 2) this.closeWindow()
            break
          case 2:
            if (this.getDirection() == 1) this.closeWindow()
            break
          case 3:
            if (this.getDirection() == 4) this.closeWindow()
            break
          case 4:
            if (this.getDirection() == 3) this.closeWindow()
            break
        }
      } else {
        switch (this.direction) {
          case 1:
            this.transform = 'translateY(-100vh)'
            break
          case 2:
            this.transform = 'translateY(100vh)'
            break
          case 3:
            this.transform = 'translateX(-100vw)'
            break
          case 4:
            this.transform = 'translateX(100vw)'
            break
        }

        setTimeout(() => {
          this.isShow = true
        }, 300)
      }
    },

    getDirection() {
      let result = 0

      if (Math.abs(this.moveX) < 2 && Math.abs(this.moveY) < 2) {
        return result
      }

      const angle = (Math.atan2(this.moveY, this.moveX) * 180) / Math.PI

      if (angle >= -45 && angle < 45) {
        result = 4
      } else if (angle >= 45 && angle < 135) {
        result = 2
      } else if (angle >= -135 && angle < -45) {
        result = 1
      } else if ((angle >= 135 && angle <= 180) || (angle >= -180 && angle < -135)) {
        result = 3
      }

      return result
    },

    closeWindow() {
      this.transform = 'translateX(0) translateY(0)'

      setTimeout(() => {
        this.isShow = false
      }, 300)
    },
  },
}
</script>

<style lang="scss">
.push-window {
  position: relative;
  height: 100vh;
  width: 100vw;
  overflow: hidden;

  &::before {
    content: '请从四周向中心滑动';
    position: absolute;
    width: 100%;
    text-align: center;
    padding-top: 38vh;
  }

  &-content {
    display: flex;
    align-items: center;
    justify-content: center;

    width: 100%;
    height: 100%;

    color: white;
    background-color: black;
    transition: transform 0.3s;

    position: absolute;

    &.from_bottom {
      bottom: -100vh;
      left: 0;
    }

    &.from_left {
      top: 0;
      left: -100vw;
    }

    &.from_top {
      top: -100vh;
      left: 0;
    }

    &.from_right {
      right: -100vw;
      top: 0;
    }
  }
}
</style>
